package com.knight.spring.framework.aop;

import com.knight.spring.framework.aop.intercept.KnightMethodInvocation;
import com.knight.spring.framework.aop.support.KnightAdvisedSupport;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;


public class KnightJdkDynamicAopProxy implements KnightAopProxy, InvocationHandler {

    private KnightAdvisedSupport advised;

    public KnightJdkDynamicAopProxy(KnightAdvisedSupport config){
        this.advised = config;
    }

    @Override
    public Object getProxy() {
        return getProxy(this.getClass().getClassLoader());
    }

    @Override
    public Object getProxy(ClassLoader classLoader) {
        return Proxy.newProxyInstance(classLoader,advised.getTargetClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, advised.getTargetClass());

        KnightMethodInvocation invocation =
                new KnightMethodInvocation(proxy, advised.getTarget(), method, args, advised.getTargetClass(), chain);
        // Proceed to the joinpoint through the interceptor chain.
        return invocation.proceed();
    }
}
